#include <ncurses.h>
#include <cstdlib>
#include <locale.h>
#include <cctype>
#include <ctime>

#define FIRST_FIELD_OFFSET 0
#define SECOND_FIELD_OFFSET 26
#define VERTICAL 0
#define HORIZONTAL 1
#define PLAYER 0
#define AI 1

//##########
bool curses_started = false;
void endCurses();
void startCurses();
//##########
int Field[10][10][2];
//##########
void ClearFields();
void DrawFields();
chtype CellStatus(int );
bool PlaceShip (int, int, int, bool, bool);
bool CheckCell (int, int, bool);
bool InitGame();


//##########
int main(int argc, char **argv)
{
	srand(time(0));
	setlocale(LC_ALL, "");
	startCurses();
	start_color();
	init_pair(1, COLOR_RED, COLOR_BLACK);
	
	ClearFields();
	InitGame();
	getch();
	DrawFields();

	return 0;
}


void DrawFields()
{
	clear();
	int currCol1=4;
	int currCol2=currCol1+SECOND_FIELD_OFFSET;
	char currChar = 65;
	while (currChar<75 )
	{
		move(0,currCol1);
		printw("%c",currChar);
		move(0,currCol2);
		addch(currChar);
		currChar++;
		if (currCol1 == 0){currCol1++;}
		currCol1+=2;
		currCol2+=2;
	}

//-------------------------------------------------
	for (short currRow=0;currRow<10;currRow++)
	{
		if(currRow==9)
		{
			move(currRow+1,FIRST_FIELD_OFFSET);
			printw("%i: ", currRow+1);
			move(currRow+1,SECOND_FIELD_OFFSET);
			printw("%i: ", currRow+1);
		}
		else
		{
			move(currRow+1,FIRST_FIELD_OFFSET+1);
			printw("%i: ", currRow+1);
			move(currRow+1,SECOND_FIELD_OFFSET+1);
			printw("%i: ", currRow+1);
		}
		
//-------------------------------------------------

		for(int x=0;x<10;x++)
		{
			mvaddch(currRow+1, x*2+FIRST_FIELD_OFFSET+4, CellStatus(Field[x][currRow][0]));
		}
		

		for(int x=0;x<10;x++)
		{
			mvaddch(currRow+1, x*2+SECOND_FIELD_OFFSET+4, CellStatus(Field[x][currRow][1]));
		}

//-------------------------------------------------

		}
	refresh();
	getch();
}

void ClearFields()
{
	for (int x=0;x<10;x++)
	{
		for (int y=0;y<10;y++)
		{
			Field[x][y][0]=0;
			Field[x][y][1]=0;
		}
	}
}

bool InitGame()
{
//Игрок:
	char px;
	int py,pnumCells;
	bool pdirection;
	clear();
	move(0,0);
	printw("Введите координаты и ориентацию корабля через пробелы.");
	printw(" Для вертикального размещения корабля вводите V, для горизонтального - H.\n");
	move(2,0);
	for(int numShips=0;numShips<0;numShips++)
	{
		if(numShips>=0 && numShips<1) //четырехпалубный
		{
			pnumCells=4;
		}
		if(numShips>=1 && numShips<3) //трехпалубные
		{
			pnumCells=3;
		}
		if(numShips>=3 && numShips<6) //двухпалубные
		{
			pnumCells=2;
		}
		if(numShips>=6 && numShips<10) //однопалубные
		{
			pnumCells=1;
		}

		
		printw("Вы ставите %i-палубный корабль.\nОсталось %i кораблей.\n",pnumCells,10-numShips);
		
		char ch_pdirection;
		printw("Корабль #%i : ",numShips+1);
		scanw("%c%i %c",&px,&py,&ch_pdirection);
		//printw("%c %i\n",toupper(px),int(toupper(px)));
		
		//Не стал использовать строковые функции; milestone - 18кб
		
		while(toupper(ch_pdirection) != 'V' && toupper(ch_pdirection) != 'H' )
		{
			switch(toupper(ch_pdirection))
			{
				case ('V'):
				{
					pdirection=VERTICAL;
					break;
				}
					case ('H'):
				{
					pdirection=HORIZONTAL;
					break;
				}
				default:
				{
					{
						printw("Неправильное направление! Введите еще раз: ");
						scanw("%c",&ch_pdirection);
					}
					break;
				}
			}
		}
		
		while(PlaceShip(toupper(px)-65,py-1,pnumCells,pdirection,PLAYER)!=true)
		{
			printw("Не удалось установить корабль. Введите заново координаты и направление: ");
			scanw("%c%i %i",&px,&py,&pdirection);
		}

		while(toupper(px) > 74 || py>10 || toupper(px) < 65 || py<1)
		{
			printw("Неверно введены координаты, попробуйте еще раз: ");
			scanw("%c%i",&px,&py);
		}
		clear();
	}
	printw("Нажмите любую клавишу для продолжения...");

	
//AI:
	int ax = rand() % 10;
	int ay = rand() % 10;
	bool direction = rand() % 2;
	short numCells = 0;
	for(int numShips=0;numShips<10;numShips++)
	{
		if(numShips>=0 && numShips<1) //четырехпалубный
		{
			numCells=4;
		}
		if(numShips>=1 && numShips<3) //трехпалубные
		{
			numCells=3;
		}
		if(numShips>=3 && numShips<6) //двухпалубные
		{
			numCells=2;
		}
		if(numShips>=6 && numShips<10) //однопалубные
		{
			numCells=1;
		}
		while(PlaceShip(ax,ay,numCells,direction,AI)!=true)
		{
			ax = rand() % 10;
			ay = rand() % 10;
			direction = rand() % 2;
		}
	}
	return 0;
}

bool PlaceShip (int x, int y, int length, bool direction, bool currPlayer)
{
	bool PlacementStatus;
	bool isShipOnTheField;
	bool PlaceForShipIsFree=true;
	switch(direction)
	{
		case (VERTICAL):
		{
			// Лежат ли крайние точки корабля в поле?
			if(x<=9 && y<=9 && x>=0 && y>=0 && (y+length-1)<=9 && (y+length-1)>=0)
			{
				isShipOnTheField=true;
			}
			for(int st_length=0;st_length<length;st_length++)
			{
				if(isShipOnTheField==true && CheckCell(x,y+st_length,currPlayer)==false)
				{
					PlaceForShipIsFree=false;
				}
			}
			
			if(isShipOnTheField && PlaceForShipIsFree)
			{
				for(int st_length=0;st_length<length;st_length++)
				{
					Field[x][y+st_length][currPlayer]=1;
				}
				PlacementStatus=true;
			}
			else
			{
				PlacementStatus=false;
			}
			break;
		}
		
		case (HORIZONTAL):
		{
			if(x<=9 && y<=9 && x>=0 && y>=0 && (x+length-1)<=9 && (x+length-1)>=0)
			{
				isShipOnTheField=true;
			}
			for(int st_length=0;st_length<length;st_length++)
			{
				if(isShipOnTheField==true && CheckCell(x+st_length,y,currPlayer)==false)
				{
					PlaceForShipIsFree=false;
				}
			}
			
			if(isShipOnTheField && PlaceForShipIsFree)
			{
				for(int st_length=0;st_length<length;st_length++)
				{
					Field[x+st_length][y][currPlayer]=1;
				}
				PlacementStatus=true;
			}
			else
			{
				PlacementStatus=false;
			}
			
			break;
		}
		
		default:
		{
			printw ("ship placement error!");
			break;
		}
	}
	return PlacementStatus;
}


bool CheckCell (int x, int y, bool currPlayer)
{
	bool isCellFree=true;
	short cx,cy;
	if(x>=0 && y>=0 && x<=9 && y<=9)
	{
		for (cx=(x-1);cx<=(x+1);cx++)
		{
			for (cy=(y-1);cy<=(y+1);cy++)
			{
				if(cx>=0 && cy>=0 && cx<=9 && cy<=9)
				{
					if(Field[cx][cy][currPlayer]!=0)
					{
						isCellFree=false;
					}
				}
			}
		}
	}
	else 
	{
		isCellFree=false;
	}
	return isCellFree;
}
chtype CellStatus (int cell)
{
	chtype symbol;
	switch (cell)
		{
		case (-1):
			symbol = 'X';
			break;
		case (0):
			symbol = '0';
			break;
		case (1):
			symbol = '#' | COLOR_PAIR(1);
			break;
		case (2):
			symbol = '-';
			break;
		default:
			printw ("Incorrect state!");
			break;
		}
	return symbol;
}
//------------------------------------------

void endCurses()
{
	if (curses_started && !isendwin())
	endwin();
}


void startCurses()
{
	if (curses_started)
	{
	refresh();
	}
	else
	{
		initscr();
		cbreak();
		echo();
		intrflush(stdscr, false);
		keypad(stdscr, true);
		atexit(endCurses);
		curses_started = true;
    }
}
